package com.pactera.asmp.server.service;

import com.pactera.asmp.server.common.constants.PermissionCode;
import com.pactera.asmp.server.common.constants.ResultCode;
import com.pactera.asmp.server.common.exception.CustomException;
import com.pactera.asmp.server.dao.PermissionMapper;
import com.pactera.asmp.server.dao.RoleMapper;
import com.pactera.asmp.server.dao.RolePermissionMapper;
import com.pactera.asmp.server.entity.ResponseResult;
import com.pactera.asmp.server.entity.RoleDTO;
import com.pactera.asmp.server.pojo.Permission;
import com.pactera.asmp.server.pojo.Role;
import com.pactera.asmp.server.pojo.RolePermissionKey;
import com.pactera.asmp.server.pojo.User;
import com.pactera.asmp.server.pojo.UserRoleKey;
import com.pactera.asmp.server.utils.AssertUtil;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Override
    public ResponseResult<List<Permission>> getAllPerMissionList() {
        return ResponseResult.defaultSuccess(permissionMapper.findAll());
    }

    @Override
    public ResponseResult<List<RolePermissionKey>> getPermsByRoleId(Integer roleId) {
        AssertUtil.notNull(roleId,"角色Id不允许为空");
        return ResponseResult.defaultSuccess(this.rolePermissionMapper.findByRole(roleId));
    }

    @Override
    @Transactional
    public ResponseResult rolePermission(RoleDTO roleDTO) {
        AssertUtil.notNull(roleDTO,"参数异常");

        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (currUser == null) throw new CustomException(ResultCode.PERMISSION_EXPIRE);

        // 1.0 角色管理、授权管理只对由超级管理可见
        this.specialMenuCheck(roleDTO);

        // 1.1 只能创建小于当前登录人员角色Level的角色(Level值大，等级越小)，不包括平级
        //   只能将某一角色修改为小于当前登录人员角色Level的角色(Level值大，等级越小)，不包括平级
        //   (暂未实现) 若是修改当前登录账户的角色(即超级管理员)，那么只能修改名称等，权限及等级不能修改
        this.checkCurrUserRoleLevel(currUser.getId(),roleDTO);

        // 1.2 角色绑定菜单权限时，只能勾选当前角色LEVEL权限大于等于菜单LEVEL的（role.Level <= menu.Level）
        this.checkMenuLevel(roleDTO);

        // 1.3 角色名称、角色编号 均不允许重复
        List<RoleDTO> existList = roleMapper.getExistList(roleDTO);
        if(!CollectionUtils.isEmpty(existList)) throw new CustomException(ResultCode.BUSINESS_ROLENAME_EXISTED);

        Date now = new Date();
        Role role = new Role();
        BeanUtils.copyProperties(roleDTO,role);

        // 2. 保存角色
        if(roleDTO.getId() == null){
            role.setInsertUid(currUser.getId());
            role.setInsertTime(now);
            role.setUpdateTime(now);
            roleMapper.insert(role);
        }
        else {
            role.setUpdateTime(now);
            roleMapper.updateById(role);
        }

        // 3. 保存权限，先删除，后新增
        rolePermissionMapper.deleteByRoleId(role.getId());
        RolePermissionKey rolePermissionKey = new RolePermissionKey();
        rolePermissionKey.setRoleId(role.getId());
        for(Integer permId : roleDTO.getPermIds()){
            rolePermissionKey.setPermitId(permId);
            rolePermissionMapper.insert(rolePermissionKey);
        }
        return ResponseResult.defaultSuccess(null);
    }

    private void specialMenuCheck(RoleDTO roleDTO) {
        if(roleDTO == null) throw new CustomException(ResultCode.DATA_IS_WRONG);

        // 如果当前level不是0，且存在角色管理或授权管理，则抛出异常
        if(roleDTO.getLevel().intValue() != 0){
            // 角色管理 id=14
            // 授权管理 id=15
//            for(Integer menuId : roleDTO.getPermIds()){
//                if(menuId.intValue() == 14 || menuId.intValue() == 15 ){
//                    throw new CustomException(ResultCode.BUSINESS_MENU_LEVEL_ERR);
//                }
//            }
            List<Permission> allMenus = permissionMapper.findAll();
            // 获取角色管理或授权管理的id
            List<Permission> roleAndPerMenus = allMenus.stream().filter(permission -> PermissionCode.ROLE_MANAGEMENT.equals(permission.getCode())
                    || PermissionCode.PERMISSION_MANAGEMENT.equals(permission.getCode())).collect(Collectors.toList());
            List<Integer> permissionIds = roleAndPerMenus.stream().map(Permission::getId).collect(Collectors.toList());
            for(Integer menuId : roleDTO.getPermIds()){
                if(permissionIds.contains(menuId)){
                    throw new CustomException(ResultCode.BUSINESS_MENU_LEVEL_ERR);
                }
            }
        }
    }

    private void checkMenuLevel(RoleDTO roleDTO) {
        if(roleDTO == null) throw new CustomException(ResultCode.DATA_IS_WRONG);

        // 获取所有菜单的LEVEL
        List<Permission> allMenus = permissionMapper.findAll();
        for(Integer currLevel : roleDTO.getPermIds()){
            for (Permission menu : allMenus){
                if(menu.getLevel() == null) continue;
                if(menu.getId().intValue() == currLevel.intValue()
                    && menu.getLevel().intValue() < roleDTO.getLevel().intValue()){
                    throw new CustomException(ResultCode.BUSINESS_MENU_LEVEL_ERR);
                }
            }
        }

    }

    private void checkCurrUserRoleLevel(Integer userId,RoleDTO roleDTO) {
        if(userId == null || roleDTO == null) throw new CustomException(ResultCode.DATA_IS_WRONG);

        List<Role> currUserRoleInfo = roleMapper.getRoleByUserId(userId);
        if(CollectionUtils.isEmpty(currUserRoleInfo)) throw new CustomException(ResultCode.DATA_IS_WRONG);

        // 目前用户是单角色，如果用户角色没有更改，则直接放行
        if(currUserRoleInfo.get(0).getId() != null && roleDTO.getId() != null && currUserRoleInfo.get(0).getId().intValue() == roleDTO.getId().intValue()) return;

        for(Role role : currUserRoleInfo){
            if(role.getLevel().intValue() < roleDTO.getLevel().intValue()){
                return;
            }
        }
        throw new CustomException(ResultCode.BUSINESS_ROLE_LEVEL_ERR);
    }

    @Override
    @Transactional
    public ResponseResult delete(Integer roleId) {
        AssertUtil.notNull(roleId,"角色Id不允许为空");
        if(roleId == 1) return ResponseResult.defaultFail(-1,"Fail","不允许删除超级管理员帐号");

        User existUser = (User) SecurityUtils.getSubject().getPrincipal();
        List<Role> roles = roleMapper.getRoleByUserId(existUser.getId());
        if(CollectionUtils.isEmpty(roles)) {
            throw new CustomException(ResultCode.PERMISSION_UNAUTHORISE);
        }

        Role role = roleMapper.selectByPrimaryKey(roleId);
        if(null == role) {
            throw new CustomException(ResultCode.RESULT_DATA_NONE);
        }
        if(roles.stream().allMatch(r -> r.getLevel().intValue() > role.getLevel().intValue())) {
            throw new CustomException(ResultCode.BUSINESS_USER_CANNOT_DELETE_ROLE_ERR);
        }
        List<UserRoleKey> userRoleKeys = roleMapper.getUserRoleByRoleId(roleId);
        if(CollectionUtils.isNotEmpty(userRoleKeys)) {
            throw new CustomException(ResultCode.BUSINESS_ROLE_CANNOT_DELETED_ERR);
        }
        rolePermissionMapper.deleteByRoleId(roleId);
        roleMapper.deleteByPrimaryKey(roleId);
        return ResponseResult.defaultSuccess(null);
    }
}
